<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>文件服务器</title>
    
    <style>
        body {
            font-family: Arial, sans-serif;
            background-color: #f4f4f4;
            margin: 0;
            padding: 0;
            justify-content: center;
            align-items: center;
            height: 100vh;
        }
        header {
            background-color: #333;
            color: #fff;
            padding: 15px 0;
        }

        .container {
            display: flex;
            justify-content: space-between;
            align-items: center;
            /* max-width: 1200px; */
            margin: 0 auto;
            /* padding: 0 15px; */
        }

        .user-info {
            display: flex;
            align-items: center;
        }

        .avatar {
            width: 50px;
            height: 50px;
            border-radius: 50%;
            margin-right: 15px;
        }

        .user-details {
            display: flex;
            flex-direction: column;
        }

        .user-name {
            font-size: 1.2em;
            margin: 0;
        }

        .user-email {
            font-size: 0.9em;
            color: #ccc;
            margin: 2px 0 0;
        }

        nav ul {
            list-style: none;
            display: flex;
            margin: 0;
            padding: 0;
        }

        nav ul li {
            margin-left: 20px;
        }

        nav ul li a {
            color: #fff;
            text-decoration: none;
            padding: 5px 10px;
            transition: background-color 0.3s;
        }

        nav ul li a:hover {
            background-color: #555;
            border-radius: 5px;
        }
        .table-container {
            box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
            border-radius: 10px;
            overflow: hidden;
            /* width: 90%;
            max-width: 800px; */
            background-color: #fff;
        }

        table {
            width: 100%;
            border-collapse: collapse;
        }

        thead {
            background-color: #2b4057;
            color: #fff;
        }

        thead th {
            padding: 12px;
            text-align: left;
        }

        tbody tr:nth-child(even) {
            background-color: #f8f8f8;
        }

        tbody tr:hover {
            background-color: #f1f1f1;
        }

        tbody td {
            padding: 12px;
            border-bottom: 1px solid #ddd;
        }

        a {
            color: #007bff;
            text-decoration: none;
        }

        a:hover {
            text-decoration: underline;
        }

        .file-path {
            color: black; /* 设置文本颜色为黑色 */
            text-decoration: none; /* 默认不显示下划线 */
        }

        .file-path:hover {
            text-decoration: none; /* 鼠标悬停时也不显示下划线 */
        }

        .download-btn, .delete-btn {
            padding: 8px 12px;
            border: none;
            border-radius: 5px;
            cursor: pointer;
            transition: background-color 0.3s;
        }

        .download-btn {
            background-color: #28a745;
            color: #fff;
        }

        .download-btn:hover {
            background-color: #218838;
        }

        .delete-btn {
            background-color: #dc3545;
            color: #fff;
        }

        .delete-btn:hover {
            background-color: #c82333;
        }

        .search-container {
            display: flex;
            gap: 10px; 
            margin-top: 15px; 
        }
    
        .search-input {
            padding: 8px;
            border: 1px solid #ccc;
            border-radius: 4px;
            width: 300px; 
        }
    
        .btn-primary {
            padding: 8px 16px;
            background-color: #007bff;
            color: white;
            border: none;
            border-radius: 4px;
            cursor: pointer;
        }
    
        .btn-primary:hover {
            background-color: #0056b3;
        }
        .welcome-header {
            background: linear-gradient(to right, #46424260, #35302d); 
            color: white; 
            padding: 10px 20px;
            border-radius: 10px; 
            text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.5);
            text-align: center; 
            margin-bottom: 20px; 
        }

        .header-and-search {
            display: flex;
            align-items: center; 
            gap: 20px; 
        }

        .upload-container {
            margin-top: 20px;
            display: flex;
            align-items: center;
        }

        .upload-container input[type="file"] {
            display: none;
        }

        .upload-container button {
            padding: 8px 16px;
            background-color: #007bff;
            color: white;
            border: none;
            border-radius: 4px;
            cursor: pointer;
        }

        .upload-container button:hover {
            background-color: #0056b3;
        }
    </style>
</head>
<body>
    <header>
        <div class="header">
            <div class="user-info">
                <img src="user-avatar.jpg" alt="User Avatar" class="avatar">
                <div class="user-details">
                    <h1 class="user-name">老登</h1>
                    <p class="user-email">老登@example.com</p>
                </div>
            </div>
            <nav>
                <ul>
                    <li><a href="/file">主页</a></li>
                    <li><a href="#">预留</a></li>
                    <li><a href="#">设置</a></li>
                    <li><a href="#">登出</a></li>
                </ul>
            </nav>
        </div>
    </header>
    <div class="header-and-search">
        <h1 class="welcome-header">欢迎老登</h1>

        <div class="search-container">
            <input type="text" placeholder="搜索文件..." class="search-input">
            <button class="btn btn-primary">转到</button>
        </div>
    </div>

    <!-- 新增的上传部分 -->
    <div class="upload-container">
        <input type="file" id="fileInput" multiple style="display:none;" />
        <button class="btn btn-primary" id="uploadButton">上传文件</button>
    </div>

    <div class="container mt-5">
        <table class="table-container" id="data-table">
            <thead>
                <tr>
                    <th>大小</th>
                    <th>名称</th>
                    <th>路径</th>
                    <th>下载</th>
                    <th>删除</th>
                </tr>
            </thead>
            <tbody>
            </tbody>
        </table>
    </div>

    <script>
        // 获取当前路径
        let currentPath = '/';

        // 更新URL而不需要重新加载页面
        function updateURL(path) {
            history.pushState({}, '', `/file${path}`);
            fetchAndDisplayDirectory(path);
        }

        // 初始加载时获取根目录内容
        window.addEventListener('load', () => {
            const path = window.location.pathname.replace('/file', '') || '/';
            updateURL(path);
        });

        // 监听popstate事件，处理浏览器的前进/后退按钮
        window.addEventListener('popstate', (event) => {
            const path = window.location.pathname.replace('/file', '');
            fetchAndDisplayDirectory(path);
        });

        // 进入目录时更新URL
        function enterDirectory(dir) {
            currentPath = dir;
            updateURL(dir);
        }

        // 将字节转换为人类可读格式
        function formatBytes(bytes) {
            if (bytes === 0) return '0 B';

            const k = 1024;
            const sizes = ['B', 'KB', 'MB', 'GB', 'TB'];
            const i = Math.floor(Math.log(bytes) / Math.log(k));

            return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
        }

        // ... 现有的 JavaScript 代码 ...

        function fetchAndDisplayDirectory(dir) {
            const fullURL = window.location.origin; // 获取当前域名和端口
            const listURL = `${fullURL}/list${dir === '/' ? '//' : dir}`;
            fetch(listURL)
                .then(response => {
                    if (!response.ok) {
                        throw new Error('Network response was not ok ' + response.statusText);
                    }
                    return response.json();
                })
                .then(data => {
                    const tbody = document.querySelector('#data-table tbody');
                    tbody.innerHTML = ''; // 清空现有内容

                    data.forEach(item => {
                        const tr = document.createElement('tr');

                        // 创建 size 列
                        const sizeTd = document.createElement('td');
                        sizeTd.textContent = formatBytes(item.size); // 使用新函数格式化大小
                        tr.appendChild(sizeTd);

                        const nameTd = document.createElement('td');
                        nameTd.textContent = item.name;
                        tr.appendChild(nameTd);

                        const pathTd = document.createElement('td');
                        const pathLink = document.createElement('a');
                        if (item.is_dir) {
                            // 如果是文件夹，在路径后面添加斜杠
                            pathLink.textContent = item.path + '/';
                            // 添加点击事件
                            pathLink.addEventListener('click', (event) => {
                                event.preventDefault(); // 阻止默认的链接行为
                                enterDirectory(item.path);
                            });
                            pathLink.style.cursor = 'pointer'; // 显示手指指针
                        } else {
                            // 如果是文件
                            pathLink.textContent = item.path;
                            pathLink.className = 'file-path'; // 应用新的样式
                        }

                        pathTd.appendChild(pathLink);
                        tr.appendChild(pathTd);

                        const button_download = document.createElement('button');
                        button_download.textContent = "下载";
                        button_download.className = "download-btn";
                        if (!item.is_dir) { // 只有文件才有下载按钮
                            button_download.addEventListener('click', (event) => downloadFile(item.path));
                        } else {
                            button_download.disabled = true; // 文件夹没有下载按钮
                        }
                        const td1 = document.createElement('td');  
                        td1.appendChild(button_download);        
                        tr.appendChild(td1);    

                        const button_delete = document.createElement('button');
                        button_delete.textContent = "删除";
                        button_delete.className = "delete-btn";
                        button_delete.addEventListener('click', () => deleteItem(item.path, item.is_dir));
                        const td2 = document.createElement('td');  
                        td2.appendChild(button_delete);        
                        tr.appendChild(td2);        

                        tbody.appendChild(tr);
                    });
                })
                .catch(error => {
                    console.error('There was a problem with your fetch operation:', error);
                });
        }

        // 删除项目（文件或目录）
        async function deleteItem(path, isDir) {
            const confirmDelete = confirm(`确定要删除 "${path}" 吗？此操作不可逆！`);
            if (!confirmDelete) return;

            const fullPath = path.startsWith('/') ? path : `/${path}`;
            try {
                const response = await fetch(`${window.location.origin}/delete${fullPath}`, {
                    method: 'DELETE',
                });

                if (response.ok) {
                    alert('删除成功！');
                    // 刷新文件列表
                    const currentPath = window.location.pathname.replace('/file', '') || '/';
                    fetchAndDisplayDirectory(currentPath);
                } else {
                    const errorMessage = await response.text();
                    alert(`删除失败：${errorMessage}`);
                }
            } catch (error) {
                console.error('删除过程中发生错误:', error);
                alert('删除过程中发生错误，请检查控制台日志。');
            }
        }
        // 下载文件
        async function downloadFile(dir) {
            const fullURL = window.location.origin; // 获取当前域名和端口
            const downloadLink = `${fullURL}/download${dir}`;
            const a = document.createElement('a');
            a.href = downloadLink;
            a.download = dir.split('/').pop(); // 使用路径的最后一部分作为文件名
            document.body.appendChild(a);
            a.click();
            document.body.removeChild(a); // 清理
        }

        // 设置每个分块的大小（例如：256MB）
        const CHUNK_SIZE = 256 * 1024 * 1024;

        // 获取上传按钮和文件输入元素
        const uploadButton = document.getElementById('uploadButton');
        const fileInput = document.getElementById('fileInput');

        // 封装后的文件上传函数
        async function uploadFileWithChunks(file, currentPath) {
            let start = 0;
            let end = CHUNK_SIZE;
            let chunkIndex = 0;
            console.debug("file.size = ", file.size)
            const totalChunks = Math.ceil(file.size / CHUNK_SIZE)
            const fileNameBase = file.name;
            let allChunksUploadedSuccessfully = true;

            while (start < file.size) {
                console.debug("start = ", start)
                const chunk = file.slice(start, end);
                const formData = new FormData();
                // 使用带有后缀的文件名来区分不同的分块
                const fileName = chunkIndex === 0 ? fileNameBase : `${fileNameBase}.${chunkIndex}`;
                formData.append('file', chunk, fileName);

                try {
                    const response = await fetch(`${window.location.origin}/upload${currentPath === '/' ? '//' : currentPath}`, {
                        method: 'POST',
                        body: formData,
                    });

                    if (!response.ok) {
                        console.error('response error:', response);
                        throw new Error('上传分块失败');
                        return
                    } else {
                        console.log(`分块 ${chunkIndex}/${totalChunks} 上传成功`);
                        // 每个分块上传成功后立即尝试合并
                        await sendMergeRequest(fileNameBase, currentPath, chunkIndex);
                    }
                } catch (error) {
                    console.error('上传过程中发生错误:', error);
                    alert('文件上传过程中发生错误，请检查控制台日志。');
                    return
                }

                chunkIndex++;
                start = end;
                end = start + CHUNK_SIZE;
            }

            alert('文件所有分块上传和合并成功！');
            fetchAndDisplayDirectory(currentPath);
        }

        // 发送合并请求的辅助函数
        async function sendMergeRequest(fileNameBase, currentPath, chunkIndex) {
            console.debug("sendMergeRequest")
            try {
                const mergeResponse = await fetch(`${window.location.origin}/merge/${encodeURIComponent(`${currentPath}/${fileNameBase}`)}`, {
                    method: 'POST'
                });

                if (mergeResponse.ok) {
                    console.log(`分块 ${chunkIndex + 1} 合并成功`);
                } else {
                    console.error(`分块 ${chunkIndex + 1} 合并失败`);
                }
            } catch (error) {
                console.error('合并过程中发生错误:', error);
                alert('文件合并过程中发生错误，请检查控制台日志。');
            }
        }

        // 当点击上传按钮时，触发文件选择框
        uploadButton.addEventListener('click', () => {
            fileInput.click();
        });

        // 当文件被选择后，开始上传过程
        fileInput.addEventListener('change', async (event) => {
            const files = event.target.files;
            if (files.length === 0) return;

            // 获取当前路径作为上传目标目录
            const currentPath = window.location.pathname.replace('/file', '') || '/';

            for (let i = 0; i < files.length; i++) {
                await uploadFileWithChunks(files[i], currentPath);
            }

            fileInput.value = ''; // 清空文件输入，以便可以再次选择相同的文件进行上传
        });
    </script>
</body>
</html>